import DataSet from '@antv/data-set';
import { Tag, Word } from '../../../../src/plots/word-cloud/types';
import { processImageMask } from '../../../../src/plots/word-cloud/utils';
import { transform, wordCloud } from '../../../../src/utils/transform/word-cloud';

const { View } = DataSet;
const options = {
  type: 'tag-cloud',
  fields: ['text', 'value'],
  font: 'Impact',
  fontSize: 10,
  fontWeight: 'bold',
  rotate: 90,
  padding: 2,
  size: [800, 800],
  spiral: 'archimedean',
  timeInterval: 5000,
};
const data = ['Hello', 'world', 'normally', 'you', 'want', 'more', 'words', 'than', 'this'].map((d) => {
  return {
    text: d,
    value: 5 + Math.random() * 10,
  };
});

function basicCommon(v: Tag) {
  expect(v.hasText).toBe(true);
  expect(typeof v.text).toBe('string');
  expect(typeof v.value).toBe('number');
  expect(typeof v.font).toBe('string');
  expect(typeof v.style).toBe('string');
  expect(typeof v.weight === 'number' || typeof v.weight === 'string').toBe(true);
  expect(typeof v.rotate).toBe('number');
  expect(typeof v.size).toBe('number');
  expect(typeof v.padding).toBe('number');
  expect(typeof v.width).toBe('number');
  expect(typeof v.height).toBe('number');
  expect(typeof v.x).toBe('number');
  expect(typeof v.y).toBe('number');
}

describe('word-cloud', () => {
  // it('with data-set', () => {
  //   const dv = new View();
  //   dv.source(data).transform(options as any);
  //   // 由于生成的每个单词的 x，y 坐标是比较随机的，每次都不一样，
  //   // 所以为了测试通过，把 x，y 属性删除。
  //   function removeXY(v) {
  //     delete v.x;
  //     delete v.y;
  //   }
  //   const result1 = wordCloud(data as Word[], options as any);
  //   const result2 = dv.rows;

  //   result1.forEach(removeXY);
  //   result2.forEach(removeXY);

  //   expect(result1).toEqual(result2);
  // });

  it('default', () => {
    const result = wordCloud(data as Word[]);
    basicCommon(result[0]);
  });

  it('callback', () => {
    const common = (row: Word) => {
      expect(typeof row.text).toBe('string');
      expect(typeof row.value).toBe('number');
    };
    const font = (row: Word) => {
      common(row);
      return 'font-test';
    };
    const fontWeight = (row: Word): any => {
      common(row);
      return 'fontWeight-test';
    };
    const fontSize = (row: Word) => {
      common(row);
      return 11;
    };
    const rotate = (row: Word) => {
      common(row);
      return 22;
    };
    const padding = (row: Word) => {
      common(row);
      return 33;
    };
    const spiral = (size: [number, number]) => {
      expect(size.length).toBe(2);
      const e = size[0] / size[1];
      return (t: number) => {
        expect(typeof t).toBe('number');
        return [e * (t *= 0.1) * Math.cos(t), t * Math.sin(t)];
      };
    };

    const result = wordCloud(data as Word[], {
      font,
      fontWeight,
      fontSize,
      rotate,
      padding,
      spiral,
    });
    const firstRow = result[0];
    basicCommon(firstRow);
    expect(firstRow.font).toBe('font-test');
    expect(firstRow.weight).toBe('fontWeight-test');
    expect(firstRow.size).toBe(11);
    expect(firstRow.rotate).toBe(22);
    expect(firstRow.padding).toBe(33);
  });

  it('data is empty', () => {
    const result = wordCloud([]);
    expect(result.length).toBe(2);
  });

  it('image mask', async () => {
    const base64 =
      '';

    const img = await processImageMask(base64);
    const result = wordCloud(data as Word[], { imageMask: img });
    basicCommon(result[0]);
  });

  it('spiral is rectangular', () => {
    const result = wordCloud(data as Word[], { spiral: 'rectangular' });
    basicCommon(result[0]);
  });

  it('random is number', () => {
    const result = wordCloud(data as Word[], { random: 0.5 });
    basicCommon(result[0]);
  });

  it('random is function', () => {
    const result = wordCloud(data as Word[], { random: () => 0.5 });
    basicCommon(result[0]);
  });
});

describe('transform', () => {
  it('default', () => {
    const result = transform(data as Word[], {
      size: [800, 800],
    });
    basicCommon(result[0]);
  });

  it('image mask with size is 0', async () => {
    const base64 =
      '';

    const img = await processImageMask(base64);
    const result = transform(data as Word[], {
      size: [0, 0],
      imageMask: img,
    });

    // 画布大小为 0 时，返回的数组应为空数组，但该实现中，
    // 最终会往返回的数组中 push 进两个元素，所以最终长度为 2。
    expect(result.length).toBe(2);
  });

  it('timeInterval is 0', () => {
    const result = transform(data as Word[], {
      size: [800, 800],
      timeInterval: 0,
    });

    // 时间间隔为 0 ，也就是说不给程序运行的时间，
    // 所以最终返回的是空数据，只包含两个占位符数据。
    expect(result.length).toBe(2);
  });

  it('padding is 0', () => {
    const result = transform(data as Word[], {
      size: [800, 800],
      padding: 0,
    });
    basicCommon(result[0]);
  });

  it('rotate is 0', () => {
    const result = transform(data as Word[], {
      size: [800, 800],
      rotate: 0,
    });
    basicCommon(result[0]);
  });
});
